/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.mvc;

import java.util.List;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.zhg2yqq.wheels.mvc.plugin.FieldDecryptInterceptor;
import com.zhg2yqq.wheels.mvc.plugin.FieldEncryptInterceptor;

import cn.hutool.core.collection.CollUtil;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;

/**
 * @author zhg2yqq, 2022年12月4日
 * @version zhg2yqq v1.0
 */
@Configuration
@EnableConfigurationProperties({MybatisEncryptProperties.class, MybatisTenantProperties.class})
@MapperScan("com.zhg2yqq.wheels.**.mapper")
public class MybatisConfiguration {
    @Bean
    public FieldDecryptInterceptor fieldDecryptInterceptor(MybatisEncryptProperties encryptProperties) {
        return new FieldDecryptInterceptor(encryptProperties.getPassword());
    }

    @Bean
    public FieldEncryptInterceptor fieldEncryptInterceptor(MybatisEncryptProperties encryptProperties) {
        return new FieldEncryptInterceptor(encryptProperties.getPassword());
    }

    @Bean
    @ConditionalOnMissingBean(PaginationInnerInterceptor.class)
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        return new PaginationInnerInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean(TenantLineHandler.class)
    @ConditionalOnProperty(name = "mybatis.tenant.enable", havingValue = "true")
    public TenantLineHandler tenantLineHandler(MybatisTenantProperties tenantProperties) {
        return new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                return new StringValue(tenantProperties.getTenantId());
            }

            @Override
            public String getTenantIdColumn() {
                return tenantProperties.getTenantColumn();
            }

            @Override
            public boolean ignoreTable(String tableName) {
                if (CollUtil.isEmpty(tenantProperties.getTenantTableNames())) {
                    return true;
                }
                return tenantProperties.getTenantTableNames().stream()
                        .noneMatch(tenantTableName -> tenantTableName.equalsIgnoreCase(tableName));
            }
        };
    }

    @Bean
    @ConditionalOnMissingBean(TenantLineInnerInterceptor.class)
    @ConditionalOnBean(TenantLineHandler.class)
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantLineHandler tenantLineHandler) {
        return new TenantLineInnerInterceptor(tenantLineHandler);
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(List<InnerInterceptor> innerInterceptors) {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        for (InnerInterceptor innerInterceptor : innerInterceptors) {
            mybatisPlusInterceptor.addInnerInterceptor(innerInterceptor);
        }
        return mybatisPlusInterceptor;
    }
}
